home *** CD-ROM | disk | FTP | other *** search
- /* findcmd - a unix-like program/file finder for MS-DOS 2.x
- *
- * Bell Communications Research, 1985
- * by Vincent Hatem
- * Raritan River Software Systems Center
- * 444 Hoes Lane
- * RRC 4D-360
- * Piscataway, NJ 08854
- *
- */
-
- #include <stdio.h>
- #define CIC86
-
- /* customizing constants */
-
- #define QS '\\' /* filename separator character */
- #define DQS "\\" /* filename separator (string) */
- #define ID 0 /* always identify directory if 1 */
- #define ALL 0 /* show hidden files by default if 1 */
- #define LONG 0 /* long listing by default if 1 */
- #define COLM 0 /* 1-column listing by default if 1 */
- #define RSORT 0 /* reverse sort by default if 1 */
- #define TSORT 0 /* time sort by default if 1 */
- #define DU 0 /* include disk use by default if 1 */
-
-
- #define NAMESIZ 13 /* 12 character name + NULL */
- #define ONECS 512 /* cluster size on one-sided floppy */
- #define TWOCS 1024 /* cluster size on two-sided floppy */
- #define HARDCS 4096 /* cluster size on hard disk */
- #define SCRSIZ 23 /* scrolling size of display screen */
-
- struct dta /* DOS Disk Transfer Address table */
- {
- char reserved[21]; /* used in "find next" operation */
- char attr; /* file attribute byte */
- int ftime; /* time of last modification */
- int fdate; /* date of last modification */
- long fsize; /* file size in bytes */
- char fname[NAMESIZ]; /* filename and extension */
- };
-
- struct outbuf /* output buffer -- array of file structs */
- {
- unsigned oattr;
- unsigned odate;
- unsigned otime;
- long osize;
- char oname[NAMESIZ+1];
- } *obuf;
-
- char spath[80]; /* holds current pathname string */
-
- /* global variables and flags */
-
- int allf = ALL; /* include hidden & system files */
- int ll = LONG; /* long listing */
- int colm = COLM; /* 1-column format */
- int rev = RSORT; /* reverse sort */
- int tsrt = TSORT; /* timesort the listing */
- int usage = DU; /* print disk usage */
- int recd; /* recursive descent requested */
- int sizonly; /* only print sizes */
- int srclen; /* length of the search string */
- int totcnt=0; /* total # of entries found */
- int lstall=0; /* list all directories traversed?? */
- char srcname[15]; /* name to search for */
-
- int np; /* number of groups printed */
- int nargs; /* number of non-option arguments */
- int clsize = 0; /* size of a cluster, in bytes */
- int clmask; /* clsize-1 for rounding & chopping */
- int drive; /* code number for drive requested */
- int tsc; /* 1 if output is to console screen */
- long left; /* unused space left on disk */
- long total; /* total of sizes encountered */
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- char *s,*p;
- int c = 0;
- int nt = 0;
-
- recd=1;
-
- nargs = argc;
- tsc = toscreen(); /* find out if output is to console screen */
- obuf = (struct outbuf *)malloc(sizeof(*obuf)); /* point to free memory */
- if((*++argv)[0] == '-')
- {
- s= argv[0]+1;
- if(*s == 'a')
- {
- lstall= 1;
- argv++;
- }
- else
- {
- fprintf(stdout,"bad argument %s\n",argv);
- exit(0);
- }
- }
-
- if(argv[0] == '\0') {
- fprintf(stdout,"useage:\n findcmd [-a] filename\n");
- exit(0);
- }
- strcpy(srcname,*argv); /* save name to look for */
- if ((p=strchr(srcname,'.')) == NULL)
- strcat(srcname,".*");
- srclen= strlen(srcname);
-
- curdrv(spath); /* default to current drive */
- strcat(spath,DQS); /* start at root */
- search(spath); /* go do the hard work */
- if(totcnt)
- fprintf(stdout,"%d entries found.\n",totcnt);
- else
- fprintf(stdout,"no entries found matching string \"%s\"\n",srcname);
- exit(0);
- }
-
- getsize(path) /* get file cluster size */
- char *path;
- {
- if(clsize == 0) /* if size not already set */
- if((clsize = getcl(path)) == 0) { /* get cluster size for drive */
- fprintf(stderr,
- "Invalid drive: %c\n", *path);
- return(1);
- }
- clmask = clsize-1;
- return(0);
- }
-
- /* toscreen - find out if output is to console screen */
-
- toscreen()
- {
- struct { unsigned int ax, bx, cx, dx, si, di, ds, es;
- } r;
-
- r.ax = 0x4400;
- r.bx = 1;
- sysint(0x21, &r, &r);
- return(r.dx & 1);
- }
-
- /* search - search 'path' for filename or directory */
-
- search(path)
- char *path;
- {
- struct dta dta; /* DOS file data table */
- extern struct outbuf; /* array of file structs */
- extern int nargs; /* number of files or directories */
- int path_len; /* length of initial path */
- int z; /* char counter */
- int k = 0; /* counts number of entries found */
- char work[80]; /* working path string */
- int comp(); /* string, time comparison routine */
- int mask = 0x0010; /* attribute mask */
- long bytes = 0; /* count of disk usage this directory */
-
- if(allf)
- mask = 0x001F;
- strcpy(work,path);
- path_len = strlen(work); /* save original path length */
-
- if(!find_first(work, &dta, 0) || work[path_len-1] == QS) {
- if(work[path_len-1] != QS) {
- strcat(work, DQS); /* if path is to a directory */
- path_len++;
- }
- strcat(work,srcname); /* list everything in it */
- }
-
- if(find_first(work, &dta, mask)) {
- do {
- obuf[k].oattr = dta.attr; /* stash this entry */
- obuf[k].otime = dta.ftime;
- obuf[k].odate = dta.fdate;
- obuf[k].osize = dta.fsize;
- strcpy(obuf[k].oname, dta.fname);
-
- if(usage || sizonly) {
- if((dta.attr & 0x10) && dta.fname[0] != '.') {
- bytes += clsize; /* sum up disk usage */
- }
- else if(dta.fsize) {
- obuf[k].osize = ((dta.fsize + clmask) & (long)(~clmask));
- bytes += obuf[k].osize;
- }
- }
-
- k++;
- } while(find_next(&dta));
- }
-
- work[path_len] = NULL; /* restore directory pathname */
- if((lstall == 1) || k)
- {
- fprintf(stdout, "%s", work); /* identify the block */
- fputc(endlin(),stdout);
- }
- if(k > 0) {
- longlist(k); /* list all entries */
- fputc(endlin(),stdout); /* separate listing blocks */
- }
- totcnt += k;
- strcat(work, "*.*");
- if(find_first(work, &dta, mask)) /* else find all sub-dirs */
- do {
- if(dta.attr & 0x10 && dta.fname[0] != '.') {
- work[path_len] = 0; /* discard old name */
- for(z=0; dta.fname[z] != NULL; z++)
- dta.fname[z] = tolower(dta.fname[z]);
- strcat(work, dta.fname); /* install a new one */
- strcat(work, DQS);
- search(work); /* and recurse */
- }
- } while(find_next(&dta));
- return;
- }
-
- /* find_first - find first file in chosen directory */
-
- find_first(path, dta, mask)
- char *path;
- struct dta *dta;
- int mask;
- {
- struct { int ax, bx, cx;
- char *dx;
- int si, di, ds, es;
- } r;
- extern int _showds();
-
- r.ax = 0x1A00; /* DOS interrupt 1A */
- r.dx = (char *)dta;
- r.ds = _showds();
- sysint(0x21, &r, &r); /* sets data transfer address */
-
- r.ax = 0x4E00; /* DOS interrupt 4E */
- r.cx = mask;
- r.dx = path;
- r.ds = _showds();
- return(!(sysint(0x21, &r, &r) & 1)); /* fills the structure */
- }
-
- /* find_next - find the next file in the same directory */
-
- find_next(dta)
- struct dta *dta;
- {
- struct { int ax, bx, cx;
- char *dx;
- int si, di, ds, es;
- } r;
- extern int _showds();
-
- r.ax = 0x1A00;
- r.dx = (char *)dta;
- r.ds = _showds();
- sysint(0x21, &r, &r); /* set dta */
-
- r.ax = 0x4F00;
- return(!(sysint(0x21, &r, &r) & 1)); /* fill the table */
- }
-
- /* curdrv - get current default drive */
-
- curdrv(sp)
- char *sp;
- {
- struct { int ax, bx, cx;
- char *dx, *si, *di, *ds, *es;
- } r;
-
- r.ax = 0x1900; /* DOS interrupt 19 */
- sysint(0x21, &r, &r); /* gets current drive number */
- *sp++ = r.ax + 'a'; /* convert to symbolic drive name */
- *sp++ = ':';
- return;
- }
-
- /* getpath - get path to directory on indicated drive */
-
- getpath(sp)
- char *sp;
- {
- struct { int ax, bx, cx, dx;
- char *si;
- int di, ds, es;
- } r;
- extern int _showds();
-
- strcat(sp, DQS); /* append root file symbol to drive name */
-
- r.ax = 0x4700; /* DOS interrupt 47 gets path string */
- r.dx = *sp - '`'; /* convert drive name to index */
- r.ds = _showds();
- r.si = sp + 3; /* paste string after root symbol */
- sysint(0x21, &r, &r);
- return;
- }
-
- /* getcl - get cluster size & space left on requested drive */
-
- getcl(pp)
- char *pp;
- {
- struct { int ax, bx, cx, dx, si, di, ds, es;} r;
- int cs;
- extern long left;
- extern int drive;
-
- if(*(pp+1) == ':') /* use specified drive if any */
- r.ax = *pp - 'a';
- else {
- r.ax = 0x1900; /* else get code for default drive */
- sysint(0x21, &r, &r);
- }
- drive = r.ax & 0x7F;
- if(!usage && !sizonly && drive == 2)
- return(HARDCS);
- else {
- r.dx = drive + 1; /* 0 = default, 1 = a, etc */
- r.ax = 0x3600;
- sysint(0x21, &r, &r); /* DOS interrupt hex 36 */
- if(r.ax == 0xFFFF) /* gets free disk space */
- return(0); /* and other goodies */
- else {
- cs = r.ax * r.cx; /* r.ax = sectors/cluster */
- left = (long)cs * r.bx; /* r.bx = # unused clusters */
- return(cs); /* r.cx = bytes/sector */
- } /* r.dx = drive capacity (clusters) */
- }
- }
-
- /* comp - compare size of two entries */
-
- comp(a,b)
- struct outbuf *a, *b;
- {
- int y;
-
- if(tsrt) {
- if(a->odate != b->odate) /* if dates differ */
- y = (a->odate < b->odate) ? -1 : 1; /* that settles it */
- else
- y = (a->otime < b->otime) ? -1 : 1; /* else compare times */
- return((rev) ? y : -y);
- }
- else {
- y = strcmp(a->oname, b->oname); /* name comparison */
- return((rev) ? -y : y);
- }
- }
-
- /* shortlist - print a list of names in 5 columns */
-
- shortlist(k)
- int k; /* total number to print */
- {
- int i, m, n;
-
- if(colm)
- n = k; /* set for 1-column listing */
- else
- n = (k + 4)/5; /* or 5-column */
-
- for(i=0; i < n; i++){
- for(m = 0; (i+m) < k; m += n) {
- if(obuf[i+m].oattr & 0x10)
- strcat(obuf[i+m].oname, DQS); /* mark directories */
- putname(i+m); /* print the name */
- fputs(" ", stdout);
- }
- fputc(endlin(),stdout);
- }
- return;
- }
-
- /* putname - convert name to lower case and print */
-
- putname(i)
- int i;
- {
- int c, j = 0;
-
- while((c = tolower(obuf[i].oname[j])) != 0) {
- fputc(c, stdout);
- j++;
- }
- while(j++ < NAMESIZ - 1) /* pad to columnarize */
- fputc(' ', stdout);
- }
-
- /* endlin - end a line and watch for screen overflow */
-
- static int lc = 0; /* line counter */
-
- endlin(fp)
- FILE *fp;
- {
- extern int tsc; /* true if output is to screen */
- int c;
-
- if(tsc && ++lc >= SCRSIZ) { /* pause if output is to console screen */
- fputs("\n--More--", fp); /* and we've shown a screenful */
- c = ci();
- fputs("\n", fp);
- switch(c) {
- case '\r': /* <RETURN> - show 1 more line */
- lc = SCRSIZ - 1;
- break;
- case 'q': /* quit with "q" or "ctrl-C" */
- case '\003':
- exit(0);
- default:
- lc = 0; /* else show another screenful */
- break;
- }
- return('\b');
- }
- else
- return('\n');
- }
-
- /* longlist - list everything about files in two columns */
-
- struct llst { /* structure to hold file information */
- char *fattr; /* file attribute pointer */
- long size; /* file size */
- int day; /* the day of creation */
- int mnum; /* month number */
- int yr;
- int hh; /* creation times */
- int mm;
- int ap; /* am or pm */
- } l;
-
- longlist(k)
- int k; /* total number to list */
- {
-
- int i, m, n, cdate;
- char *mon, *mname();
-
- cdate = gcdate(); /* get current date (in months) */
- n = k; /* set for 1 column listing */
- for(i=0; i < n; i++){
- for(m = 0; (m+i) < k; m += n) {
- fill(i+m, &l); /* fill llst structure */
- mon = mname(l.mnum); /* conv month # to name */
- fprintf(stdout, "%s%7ld %2d %s ",
- l.fattr, l.size, l.day, mon);
- if(cdate >= (l.yr * 12 +l.mnum) + 12)
- fprintf(stdout, " %4d ", l.yr); /* print year if too old */
- else {
- fprintf(stdout, "%2d:%02d%c ",
- l.hh, l.mm, l.ap); /* else print time */
- }
- putname(i+m);
- if(m+n < k)
- fputs("\272 ", stdout); /* double bar separator */
- }
- fputc(endlin(),stdout);
- }
- return;
- }
-
- /* fill - fill long list structure with file information */
-
- fill(i, ll)
- int i;
- struct llst *ll;
- {
- int j, k;
- static char fbuf[16][4] = {
- "--w",
- "---",
- "-hw",
- "-h-",
- "s-w",
- "s--",
- "shw",
- "sh-",
- "d-w",
- "d--",
- "dhw",
- "dh-",
- "d-w",
- "d--",
- "dhw",
- "dh-"
- };
-
- if((obuf[i].oattr & 0x10) && obuf[i].oname[0] != '.') {
- ll->size = clsize;
- j = 8; /* if directory, use block size */
- } /* and set dir attr offset */
- else {
- ll->size = obuf[i].osize; /* else use file size */
- j = 0; /* and file attr offset */
- }
- ll->fattr = fbuf[(obuf[i].oattr & 0x07) + j]; /* point to symbolic attr */
- ll->day = obuf[i].odate & 0x1F;
- ll->mnum = (obuf[i].odate >> 5) & 0x0F;
- ll->yr = (obuf[i].odate >> 9) + 1980;
- k = obuf[i].otime >> 5; /* this is a mess */
- ll->mm = k & 0x3f;
- ll->ap = ((ll->hh = k >> 6) >= 12) ? 'p' : 'a';
- if(ll->hh > 12)
- ll->hh -= 12;
- if(ll->hh == 0)
- ll->hh = 12;
- return;
- }
-
-
- /* gcdate - get current date (in months) for comparison */
-
- gcdate()
- {
- struct { unsigned int ax, bx, cx, dx, si, di, ds, es;} r;
-
- r.ax = 0x2A00;
- sysint(0x21, &r, &r);
- return(r.cx * 12 + (r.dx >> 8)); /* yr * 12 + month */
- }
-
- /* mname - convert month number to month name */
-
- char *mname(n)
- int n;
- {
- static char *name[] = {
- "???",
- "Jan",
- "Feb",
- "Mar",
- "Apr",
- "May",
- "Jun",
- "Jul",
- "Aug",
- "Sep",
- "Oct",
- "Nov",
- "Dec"
- };
- return((n < 1 || n > 12) ? name[0] : name[n]);
- }
-
- #ifdef CIC86
-
- _showds()
- {
- struct{int cs, ss, ds, es;} r;
-
- segread(&r);
- return(r.ds);
- }
-
- ci()
- {
- return(bdos(7) & 0xFF);
- }
-
- #endif
-